/**
 * 
 */
package spitfire.ksim.view;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import spitfire.ksim.simulation.KSimulation;
import spitfire.ksim.simulator.KSimTimeElapseListener;
import spitfire.ksim.simulator.KSimulator;
import spitfire.ksim.simulator.KStateChangeListener;

/**
 * @author Adam
 * 
 */
public class KSimulationView extends JFrame implements KStateChangeListener {

	private static final long serialVersionUID = 4643426532596519018L;
	private KSimulation simulation;
	private KNetworkFrame netFrame;
	private KNetworkView netView;
	private KToolFrame tunersFrame; 
	// Menu stuff
	private JMenuBar mnBar = new JMenuBar();
	private JMenu mnSystem = new JMenu("System");
	private JMenu mnScene = new JMenu("Scene");
	private JMenu mnControl = new JMenu("Control");
	private JMenu mnHelp = new JMenu("Help");
	private JMenuItem mniStartSim = new JMenuItem("Start simulation");
	private JMenuItem mniPauseSim = new JMenuItem("Pause simulation");
	private JMenuItem mniResumeSim = new JMenuItem("Resume simulation");
	private JMenuItem mniStopSim = new JMenuItem("Stop simulation");
	private JMenuItem mniResetSim = new JMenuItem("Reset simulation");
	private JMenuItem mniExit = new JMenuItem("Exit");
	private JMenuItem mniNewScene = new JMenuItem("Generate scenario");
	private JMenuItem mniLoadScene = new JMenuItem("Load scenario");
	private JMenuItem mniSaveScene = new JMenuItem("Save scenario");
	private JMenuItem mniTuners = new JCheckBoxMenuItem("Tuners pane", false);
	private JMenuItem mniAbout = new JMenuItem("About");

	public KSimulationView(KSimulation sim) {
		super("Wireless Sensor Network Simulator");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setContentPane(new JDesktopPane());
		setPreferredSize(new Dimension(1280, 600));
		pack();
		setVisible(true);
		
		// NetworkFrame
		netFrame = new KNetworkFrame("", true, false, true, true);
		netView = new KNetworkView(this);
		netFrame.add(netView);
		add(netFrame);
		setSimulation(sim);
		netFrame.pack();
		netFrame.setVisible(true);
		// TunersFrame
		tunersFrame = new KTunersFrame(this);
		tunersFrame.addInternalFrameListener(new InternalFrameAdapter() {
			@Override
			public void internalFrameClosing(InternalFrameEvent e) {
				super.internalFrameClosing(e);
				mniTuners.setSelected(false);
			}
		});
		add(tunersFrame);

		// Menu stuff
		setJMenuBar(mnBar);
		mnBar.add(mnSystem);
		mnBar.add(mnScene);
		mnBar.add(mnControl);
		mnBar.add(mnHelp);
		mnSystem.add(mniStartSim);
		mniStartSim.setEnabled(true);
		mnSystem.add(mniPauseSim);
		mniPauseSim.setEnabled(false);
		mnSystem.add(mniResumeSim);
		mniResumeSim.setEnabled(false);
		mnSystem.add(mniStopSim);
		mniStopSim.setEnabled(false);
		mnSystem.add(mniResetSim);
		mniResetSim.setEnabled(true);
		mnSystem.add(mniExit);
		mniExit.setEnabled(true);
		mnScene.add(mniNewScene);
		mniNewScene.setEnabled(true);
		mnScene.add(mniLoadScene);
		mniLoadScene.setEnabled(true);
		mnScene.add(mniSaveScene);
		mniSaveScene.setEnabled(true);
		mnControl.add(mniTuners);
		mniTuners.setEnabled(true);
		mnHelp.add(mniAbout);
		mniAbout.setEnabled(true);

		// menuItem listeners
		mniStartSim.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				simulation.startSimulation();
			}
		});

		mniPauseSim.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				simulation.pauseSimulation();
			}
		});

		mniResumeSim.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				simulation.resumeSimulation();
			}
		});

		mniStopSim.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				simulation.stopSimulation();
			}
		});

		mniResetSim.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				resetSimulation();
				netView.repaint();
			}
		});

		mniExit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				System.exit(0);
			}
		});
		
		mniNewScene.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				netView.popNewSceneClick(event);
			}
		});

		mniSaveScene.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				netView.popSaveSceneClick(event);
			}
		});

		mniLoadScene.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				netView.popLoadSceneClick(event);
			}
		});
		
		mniTuners.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(mniTuners.isSelected()) {
					tunersFrame.setVisible(true);
				} else {
					tunersFrame.setVisible(false);
				}
			}
		});
	}

	@Override
	public void stateChanged() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				if (simulation.isPaused()) {
					mniPauseSim.setEnabled(false);
					mniResumeSim.setEnabled(true);
				} else {
					if (simulation.isStopped()) {
						mniPauseSim.setEnabled(false);
					} else {
						mniPauseSim.setEnabled(true);
					}
					mniResumeSim.setEnabled(false);
				}
				if (simulation.isStopped()) {
					mniStartSim.setEnabled(true);
					mniStopSim.setEnabled(false);
				} else {
					mniStartSim.setEnabled(false);
					mniStopSim.setEnabled(true);
				}
			}
		});
	}

	/**
	 * 
	 */
	public void resetSimulation() {
		simulation.destroy();
		setSimulation(new KSimulation());
	}

	/**
	 * 
	 */
	public void setSimulation(KSimulation sim) {
		simulation = sim;
		netView.setSimulation(simulation);
		final KSimulator simulator = simulation.getSimulator();
		final DateFormat df = DateFormat.getDateTimeInstance();
		String title = "Start: " + df.format(simulator.getStartTime())
				+ " | End: " + df.format(simulator.getEndTime()) + " | Now: "
				+ df.format(simulator.getSimTime());
		netFrame.setTitle(title);
		simulator.addStateChangeListener(this);
		simulator.addSimTimeElapseListener(new KSimTimeElapseListener() {
			@Override
			public void timeElapsed() {
				final String title = "Start: " + df.format(simulator.getStartTime())
						+ " | End: " + df.format(simulator.getEndTime())
						+ " | Now: " + df.format(simulator.getSimTime());
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						netFrame.setTitle(title);
					}
				});
			}
		});
	}
	
	public KSimulation getSimulation() {
		return simulation;
	}
}
